<?php

/**
 * Ueditor插件
 * @author Nintendov
 */

namespace App\Service\Ueditor;

use Illuminate\Support\Facades\Config;
use Qiniu\Auth;
use Qiniu\Storage\UploadManager;

class Ueditor
{

    //public $uid;//要操作的用户id 如有登录需要则去掉注释

    private $output;//要输出的数据

    private $st;

    private $rootpath = "../../cdn";

    public function __construct($uid = '')
    {
        //uid 为空则导入当前会话uid
        //if(''===$uid) $this->uid = session('uid');

        \App\Service\Ueditor\Vin\FileStorage::connect('File');
        //导入设置
        //$CONFIG = json_decode(preg_replace("/\/\*[\s\S]+?\*\//", "", file_get_contents(CONF_PATH."ueditor.json")), true);
        $CONFIG = json_decode(preg_replace("/\/\*[\s\S]+?\*\//", "", file_get_contents("../config/ueditor.json")), true);
        $action = htmlspecialchars($_GET['action']);

        switch($action){
            case 'config':
                $result = json_encode($CONFIG);
                break;

            case 'uploadimage':
                $config    = array(
                    "pathFormat" => $CONFIG['imagePathFormat'],
                    "maxSize"    => $CONFIG['imageMaxSize'],
                    "allowFiles" => $CONFIG['imageAllowFiles'],
                );
                $fieldName = $CONFIG['imageFieldName'];
                $result    = $this->uploadFile($config, $fieldName);
                break;

            case 'uploadscrawl':
                $config    = array(
                    "pathFormat" => $CONFIG['scrawlPathFormat'],
                    "maxSize"    => $CONFIG['scrawlMaxSize'],
                    "allowFiles" => $CONFIG['scrawlAllowFiles'],
                    "oriName"    => "scrawl.png",
                );
                $fieldName = $CONFIG['scrawlFieldName'];
                $result    = $this->uploadBase64($config, $fieldName);
                break;

            case 'uploadvideo':
                $config    = array(
                    "pathFormat" => $CONFIG['videoPathFormat'],
                    "maxSize"    => $CONFIG['videoMaxSize'],
                    "allowFiles" => $CONFIG['videoAllowFiles'],
                );
                $fieldName = $CONFIG['videoFieldName'];
                $result    = $this->uploadFile($config, $fieldName);
                break;

            case 'uploadfile':
                // default:
                $config    = array(
                    "pathFormat" => $CONFIG['filePathFormat'],
                    "maxSize"    => $CONFIG['fileMaxSize'],
                    "allowFiles" => $CONFIG['fileAllowFiles'],
                );
                $fieldName = $CONFIG['fileFieldName'];
                $result    = $this->uploadFile($config, $fieldName);
                break;

            case 'listfile':
                $config = array(
                    'allowFiles' => $CONFIG['fileManagerAllowFiles'],
                    'listSize'   => $CONFIG['fileManagerListSize'],
                    'path'       => $CONFIG['fileManagerListPath'],
                );
                $result = $this->listFile($config);
                break;

            case 'listimage':
                $config = array(
                    'allowFiles' => $CONFIG['imageManagerAllowFiles'],
                    'listSize'   => $CONFIG['imageManagerListSize'],
                    'path'       => $CONFIG['imageManagerListPath'],
                );
                $result = $this->listFile($config);
                break;

            case 'catchimage':
                $config    = array(
                    "pathFormat" => $CONFIG['catcherPathFormat'],
                    "maxSize"    => $CONFIG['catcherMaxSize'],
                    "allowFiles" => $CONFIG['catcherAllowFiles'],
                    "oriName"    => "remote.png",
                );
                $fieldName = $CONFIG['catcherFieldName'];
                $result    = $this->saveRemote($config, $fieldName);
                break;

            default:
                $result = json_encode(array(
                    'state' => 'wrong require',
                ));
                break;

        }

        if(isset($_GET["callback"])){
            if(preg_match("/^[\w_]+$/", $_GET["callback"])){
                $this->output = htmlspecialchars($_GET["callback"]).'('.$result.')';
            } else{
                $this->output = json_encode(array(
                    'state' => 'callback参数不合法',
                ));
            }
        } else{
            $this->output = $result;
        }
    }


    /**
     *
     * 输出结果
     * @param data 数组数据
     * @return 组合后json格式的结果
     */
    public function output()
    {
        return $this->output;
    }

    /**
     * 上传文件方法
     *
     */
    // 上传七牛云（并压缩图片在上传）
    public function uploadFile()
    {
        $file = request()->file('upfile');
        if(!$file->isValid()){
            return ["state" => $file->getError()];
        }

        // 验证图片后缀
        //$entension = strtolower($file->getExtension());  // 上传文件的后缀.
        $entension = strtolower($file->getClientOriginalExtension());  // 上传文件的后缀.
        $images    = ['bmp', 'dib', 'pcp', 'dif', 'wmf', 'jpg', 'tif', 'eps', 'cdr', 'iff', 'tga', 'pcd', 'mpt', 'png', 'jpeg', 'psd', 'tiff', 'bnp']; // 'gif',
        $voices    = ['mp3', 'wav', 'wma', 'mp2', 'flac', 'midi', 'ra', 'ape', 'aac', 'cda', 'mov'];
        if($entension == 'gif'){
            return ["state" => '请不要上传gif文件！！'];
        }


        $is_pic   = in_array($entension, $images);
        $is_voice = in_array($entension, $voices);
        $fileName = $file->getPathname();
        if((!$is_pic) && (!$is_voice)){
            return ["state" => '请上传正确的文件格式！！'];
        }


        // 获取文件内容 在百度验证
        if($is_pic){
            //$content = $file->getContent();
            //$this->baiduImageCensor($realPath); // 百度审核，两种传值都可以
            //$this->baiduImageCensor($file); // 百度审核，两种传值都可以
        }


        // 上传参数
        $to        = 'app/'.date('Y/Ym/d/').date('Ymd').microtime(true).mt_rand().'.'.$entension;
        $qiUpload  = new UploadManager();
        $accessKey = config('filesystems.disks.qiniu.access_key');
        $secretKey = config('filesystems.disks.qiniu.secret_key');
        $bucket    = config('filesystems.disks.qiniu.bucket');//上传空间名称

        // 上传
        $auth  = new Auth($accessKey, $secretKey);
        $token = $auth->uploadToken($bucket);
        $res   = $qiUpload->putFile($token, $to, $fileName, null, $file->getMimeType(), false);

        // 压缩 在上传
        if($is_pic){
            $to_local = $fileName.'_thumb.jpg';
            $to_to    = $to.'_thumb.jpg';
            $this->toCompress($fileName, $to_local);
            $res = $qiUpload->putFile($token, $to_to, $to_local, null, $file->getMimeType(), false);
        }

        // 组合域名地址
        $domain = Config::get('site.cdnHost');
        if(substr($domain, -1) != '/'){
            $domain = $domain.'/';
        }
        $to = $domain.$to;

        $data = [
            //'url'=>\Vin\FileStorage::getPath($rootpath,$info['savepath'].$info['savename']),
            'state'    => "SUCCESS",
            'url'      => $domain.$to_to,
            'title'    => $file->getClientOriginalName(),
            'original' => $file->getClientOriginalName(),
            'type'     =>  $file->getMimeType(),
            'size'     => $file->getSize(),
        ];

        return json_encode($data);
    }

    private function uploadFile2($config, $fieldName)
    {
        $upload          = new \Think\Upload(C('UPLOAD_SITEIMG_QINIU'));
        $upload->maxSize = $config['maxSize'];// 设置附件上传大小
        $upload->exts    = $this->format_exts($config['allowFiles']);// 设置附件上传类型

        //$upload->rootPath  =     $this->rootpath; // 设置附件上传根目录
        //$upload->autoSub = false;
        //$upload->savePath  =     $this->getFullPath($config['pathFormat']); // 设置附件上传（子）目录
        //$info=$upload->uploadOne($_FILES[$fieldName]);
        //$info=$upload->uploadOne($_FILES);
        $info     = $upload->upload($_FILES);
        $rootpath = $this->rootpath;

        if(!$info){
            $data = array(
                "state" => $upload->getError(),
            );
        } else{
            $info = $info['upfile'];
            $data = array(
                'state'    => "SUCCESS",
                //'url'=>\Vin\FileStorage::getPath($rootpath,$info['savepath'].$info['savename']),
                'url'      => urldecode($info['url'].'?imageMogr2/auto-orient/thumbnail/750x>'),
                'title'    => $info['savename'],
                'original' => $info['savename'],
                'type'     => '.'.$info['ext'],
                'size'     => $info['size'],
            );
        }

        return json_encode($data);
    }

    // 自己写的压缩文件方法
    protected function toCompress($file, $toFile)
    {
        // 图片信息
        $splFile  = new \SplFileInfo($file);
        $filePath = $splFile->getPathname();
        //获取图像信息
        $info = @getimagesize($filePath);
        $type = image_type_to_extension($info[2], false);
        $fun  = "imagecreatefrom{$type}";
        $im   = @$fun($filePath);

        // 新图片高与宽
        $width     = $info[0];
        $height    = $info[1];
        $to_width  = 500;
        $to_height = $height * $to_width / $width;

        // 制作等比例图片
        if($width > $to_width){
            //创建新图像
            $x   = $y = 0;
            $img = imagecreatetruecolor($to_width, $to_height);
            imagesavealpha($img, true); //这里很重要 意思是不要丢了$sourePic图像的透明色
            $color = imagecolorallocatealpha($img, 255, 255, 255, 127);
            imagefill($img, 0, 0, $color);
            // 裁剪
            imagecopyresampled($img, $im, 0, 0, $x, $y, $to_width, $to_height, $width, $height);
            imagedestroy($im); //销毁原图
            // 新突破
            $im = $img;
        }

        // 保存图片
        imageinterlace($im, 1);  // 间隔扫描 1-提升质量
        imagejpeg($im, $toFile, 70);  // 图片质量70
        imagedestroy($im);

        return $toFile;
    }

    /**
     *
     * Enter description here ...
     */
    private function uploadBase64($config, $fieldName)
    {
        $data = array();

        $base64Data = $_POST[$fieldName];
        $img        = base64_decode($base64Data);
        $path       = $this->getFullPath($config['pathFormat']);

        if(strlen($img) > $config['maxSize']){
            $data['states'] = 'too large';

            return json_encode($data);
        }

        $rootpath = $this->rootpath;

        //替换随机字符串
        $imgname  = uniqid().'.png';
        $filename = $path.$imgname;

        if(\Vin\FileStorage::put($rootpath, $filename, $img)){
            $data = array(
                'state'    => 'SUCCESS',
                'url'      => \Vin\FileStorage::getPath($rootpath, $filename),
                'title'    => $imgname,
                'original' => 'scrawl.png',
                'type'     => '.png',
                'size'     => strlen($img),

            );
        } else{
            $data = array(
                'state' => 'cant write',
            );
        }

        return json_encode($data);
    }

    /**
     * 列出文件夹下所有文件，如果是目录则向下
     */
    private function listFile($config)
    {
        $allowFiles = substr(str_replace(".", "|", join("", $config['allowFiles'])), 1);
        $size       = isset($_GET['size']) ? htmlspecialchars($_GET['size']) : $config['listSize'];
        $start      = isset($_GET['start']) ? htmlspecialchars($_GET['start']) : 0;
        $end        = $start + $size;

        $rootpath = $this->rootpath;

        $path  = $config['path'];
        $files = \Vin\FileStorage::listFile($rootpath, $path, $allowFiles);
        //return $files;
        if(!count($files)){
            return json_encode(array(
                "state" => "no match file",
                "list"  => array(),
                "start" => $start,
                "total" => count($files),
                "path"  => $path,
            ));
        }

        /* 获取指定范围的列表 */
        $len = count($files);
        for($i = min($end, $len) - 1, $list = array(); $i < $len && $i >= 0 && $i >= $start; $i--){
            $list[] = $files[$i];
        }
        //倒序
        //for ($i = $end, $list = array(); $i < $len && $i < $end; $i++){
        //    $list[] = $files[$i];
        //}

        /* 返回数据 */
        $result = json_encode(array(
            "state" => "SUCCESS",
            "list"  => $list,
            "start" => $start,
            "total" => count($files),
            "path"  => $path,
        ));

        return $result;
    }

    /**
     *
     * Enter description here ...
     */
    private function saveRemote($config, $fieldName)
    {
        $list = array();
        if(isset($_POST[$fieldName])){
            $source = $_POST[$fieldName];
        } else{
            $source = $_GET[$fieldName];
        }
        foreach($source as $imgUrl){
            $imgUrl = htmlspecialchars($imgUrl);
            $imgUrl = str_replace("&amp;", "&", $imgUrl);

            //http开头验证
            if(strpos($imgUrl, "http") !== 0){
                $data = array('state' => '不是http链接');

                return json_encode($data);
            }
            //格式验证(扩展名验证和Content-Type验证)
            $fileType = strtolower(strrchr($imgUrl, '.'));
            if(!in_array($fileType, $config['allowFiles']) || stristr($heads['Content-Type'], "image")){
                $data = array("state" => "错误文件格式");

                return json_encode($data);
            }

            //打开输出缓冲区并获取远程图片
            ob_start();
            $context = stream_context_create(
                array(
                    'http' => array(
                        'follow_location' => false // don't follow redirects
                    ),
                )
            );
            readfile($imgUrl, false, $context);
            $img = ob_get_contents();
            ob_end_clean();
            preg_match("/[\/]([^\/]*)[\.]?[^\.\/]*$/", $imgUrl, $m);

            $path = $this->getFullPath($config['pathFormat']);
            if(strlen($img) > $config['maxSize']){
                $data['states'] = 'too large';

                return json_encode($data);
            }

            $rootpath = $this->rootpath;

            $imgname  = uniqid().'.png';
            $filename = $path.$imgname;

            $oriName = $m ? $m[1] : "";

            if(\Vin\FileStorage::put($rootpath, $filename, $img)){
                /*array_push($list, array(
                    "state" => 'SUCCESS',
                    "url" => \Vin\FileStorage::getPath($rootpath,$filename),
                    "size" => strlen($img),
                    "title" => $imgname,
                    "original" => $oriName,
                    "source" => htmlspecialchars($imgUrl)
                ));*/
                array_push($list, array(
                    "state"    => 'SUCCESS',
                    "url"      => htmlspecialchars($imgUrl),
                    "size"     => strlen($img),
                    "title"    => $imgname,
                    "original" => $oriName,
                    "source"   => \Vin\FileStorage::getPath($rootpath, $filename),
                ));
            } else{
                array_push($list, array('state' => '文件写入失败'));
            }
        }

        /* 返回抓取数据 */

        return json_encode(array(
            'state' => count($list) ? 'SUCCESS' : 'ERROR',
            'list'  => $list,
        ));
    }

    /**
     * 规则替换命名文件
     * @param $path
     * @return string
     */
    private function getFullPath($path)
    {
        //替换日期事件
        $t      = time();
        $d      = explode('-', date("Y-y-m-d-H-i-s"));
        $format = $path;
        $format = str_replace("{yyyy}", $d[0], $format);
        $format = str_replace("{yy}", $d[1], $format);
        $format = str_replace("{mm}", $d[2], $format);
        $format = str_replace("{dd}", $d[3], $format);
        $format = str_replace("{hh}", $d[4], $format);
        $format = str_replace("{ii}", $d[5], $format);
        $format = str_replace("{ss}", $d[6], $format);
        $format = str_replace("{uid}", $this->uid, $format);

        return $format;
    }

    private function format_exts($exts)
    {
        $data = array();
        foreach($exts as $key => $value){
            $data[] = ltrim($value, '.');
        }

        return $data;
    }

}
